﻿using StableDiffusionTools.Framework;
using StableDiffusionTools.Utils;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace LoRAExplorer.Framework
{
    public class SafetensorTag
    {
        public SafetensorTag(string fileName)
        {
            FullName = fileName;
            FileName = Path.GetFileName(fileName);
            Safetensors st = Safetensors.LoadSafetensors(FullName);
            Metadata = st.Metadata;
            HasMetadata = !string.IsNullOrEmpty(Metadata);
            //if (HasMetadata)
            //{
            //    var meta = ModelMetadata.GetMetadata(Metadata);
            //    if(meta != null && meta.Modelspec_Architecture != null)
            //    {
            //        switch (meta.Modelspec_Architecture)
            //        {
            //            case "stable-diffusion-v1/lora":
            //            case "stable-diffusion-v1/textual-inversion":
            //            case "stable-diffusion-xl-v1-base/lora":
            //            case "stable-diffusion-xl-v1-base/textual-inversion":
            //                break;
            //            default:
            //                System.Diagnostics.Debug.WriteLine(meta.Modelspec_Architecture);
            //                break;
            //        }

            //    }
            //}
            var tags = st.Tags;
            if(tags != null && tags.Count > 0)
            {
                TagsDictionary = st.TagsDictionary;
                Tags = string.Join(ControlChars.CrLf, tags);
                HasTags = true;
                MaxTagLength = st.MaxTagLength;
            }
            Model = st.MetaModel;
            CoverImages = st.CoverImages;
            CoverResult = st.CoverResult.ToString();
        }

        public string FileName { get; private set; }
        public string FullName { get; private set; }
        public bool HasMetadata { get; private set; }
        public string Metadata { get; private set; }
        public string Tags { get; private set; }
        public Dictionary<string, Tuple<int, int>> TagsDictionary { get; private set; }
        public int MaxTagLength { get; private set; }
        public bool HasTags { get; private set; }
        public string Model { get; private set; }
        public Bitmap[] CoverImages { get; private set; }
        public string CoverResult { get; private set; }
        private string imagePath = null;
        public string ImagePath
        {
            get
            {
                if(imagePath == null)
                {
                    imagePath = GetImagePath();
                }
                return imagePath;
            }
            private set
            {
                imagePath = value;
            }
        }

        private string GetImagePath()
        {
            string foundPath = "";
            string path = Path.GetDirectoryName(FullName);
            string fileNameNoExt = Path.GetFileNameWithoutExtension(FullName);
            string[] imageExtensions = new string[] { "png", "jpg" , "jpeg" };
            for (int i = 0; i < imageExtensions.Length; i++)
            {
                string tryPath = Path.Combine(path, $"{fileNameNoExt}.{imageExtensions[i]}");
                if(ExtendedPathInfo.GetPathInfo(tryPath) == PathInfo.File)
                {
                    foundPath = tryPath;
                    break;
                }
            }
            return foundPath;
        }

        public void DisposeImages()
        {
            if (CoverImages != null)
            {
                for (int j = 0; j < CoverImages.Length; j++)
                {
                    CoverImages?[j].Dispose();
                }
            }
        }

        public string ExportCSV(ExportOrder selectedEnum, bool sortDescending)
        {
            StringBuilder sb = new StringBuilder();
            var sortedDict = sortDescending ? from entry in TagsDictionary orderby entry.Value.Item1 descending select entry
                                                 : from entry in TagsDictionary orderby entry.Value.Item1 ascending select entry;
            foreach (var item in sortedDict)
            {
                if (sb.Length > 0)
                    sb.AppendLine();

                switch (selectedEnum)
                {
                    case ExportOrder.Name:
                        sb.Append($"{item.Key}");
                        break;
                    case ExportOrder.Name_Count:
                        sb.Append($"{item.Key},{item.Value.Item1}");
                        break;
                    case ExportOrder.Name_Count_Repeats:
                        sb.Append($"{item.Key},{item.Value.Item1},{item.Value.Item2}");
                        break;
                }
            }
            return sb.ToString();
        }

        public string ExportTxt(ExportOrder selectedEnum, bool sortDescending)
        {
            StringBuilder sb = new StringBuilder();

            var sortedDict = sortDescending ? from entry in TagsDictionary orderby entry.Value.Item1 descending select entry
                                                 : from entry in TagsDictionary orderby entry.Value.Item1 ascending select entry;
            int maxCountLen = sortedDict.Max((k) => k.Value.Item1);
            maxCountLen = maxCountLen == 0 ? 1 : (int)Math.Floor(Math.Log10(maxCountLen)) + 1;
            foreach (var item in sortedDict)
            {
                if (sb.Length > 0)
                    sb.AppendLine();

                switch (selectedEnum)
                {
                    case ExportOrder.Name:
                        sb.Append($"{item.Key}");
                        break;
                    case ExportOrder.Name_Count:
                        sb.Append($"{item.Key.PadRight(MaxTagLength, ' ')} {item.Value.Item1}");
                        break;
                    case ExportOrder.Name_Count_Repeats:
                        sb.Append($"{item.Key.PadRight(MaxTagLength, ' ')} {item.Value.Item1.ToString().PadRight(maxCountLen)} {item.Value.Item2}");
                        break;
                }
            }
            return sb.ToString();
        }
    }
}
